/***************************************************************************
 *                                                                         *
 * Copyright (c) 2007 - 2009 Nuvoton Technology Corp. All rights reserved.*
 *                                                                         *
 ***************************************************************************/
 
#ifdef ECOS
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "drv_api.h"
#include "diag.h"
#include "wbio.h"
#include "NUC900_GE.h"
#include "NUC900_reg.h"
#else
#include <stdio.h>
#include "NUC900_GE.h"
#include "wbio.h"
#ifdef _NUC900_
#include "NUC900_reg.h"
#else
#include "reg702.h"
#endif
#endif

#define  PN   1  // Quadrant 1
#define  NN   2  // Quadrant 2
#define  NP   3  // Quadrant 3
#define  PP   4  // Quadrant 4

char _DrawMode = MODE_OPAQUE;
UINT32 _ColorKey;
UINT32 _ColorKeyMask;

BOOL _EnableAlpha = FALSE;
int _AlphaKs, _AlphaKd;


///////////////////////////////////////////////////////////////////////////////
//
// Function: set_draw_mode()
//
// Description:
//   Set BitBlt drawing mode.
//   The caller has to specify the color key and color mask 
//   for MODE_TRANSPARENT. 
//
///////////////////////////////////////////////////////////////////////////////
void set_draw_mode(int opt, int ckey, int mask)
{
  if (opt==MODE_TRANSPARENT)
  {
    _DrawMode = MODE_TRANSPARENT;
    
    _ColorKey = make_color(ckey);
    _ColorKeyMask = make_color(mask);
    
    outpw(REG_2D_GETC, _ColorKey);
    outpw(REG_2D_GETCM, _ColorKeyMask);
  }
  else if (opt==MODE_DEST_TRANSPARENT)
  {
    _DrawMode = MODE_DEST_TRANSPARENT;
    
    _ColorKey = make_color(ckey);
    _ColorKeyMask = make_color(mask);
    
    outpw(REG_2D_GETC, _ColorKey);
    outpw(REG_2D_GETCM, _ColorKeyMask);
  }
  else
  {
    _DrawMode = MODE_OPAQUE; // default is OPAQUE
  }
}


///////////////////////////////////////////////////////////////////////////////
//
// Function: set_alpha_mode()
//
// Description:
//   Set alpha blending programming. 
//   ks+kd <= 256
///////////////////////////////////////////////////////////////////////////////
void set_alpha_mode(int opt, int ks, int kd)
{
  if (opt==1)
  { 
    _EnableAlpha = TRUE;
    _AlphaKs = ks;
    _AlphaKd = kd;
  }
  else
  {
    _EnableAlpha = FALSE;
  }   
}

///////////////////////////////////////////////////////////////////////////////
//
// Function: screen_to_screen_blt()
//
// Description:
//   Screen-to-Screen BitBlt with SRCCOPY. 
//
///////////////////////////////////////////////////////////////////////////////
void screen_to_screen_blt(int srcx, int srcy, int destx, int desty, int width, int height)
{
  int direction;
  UINT32 cmd32, pitch, dest_start, src_start, dimension;
  UINT32 data32, alpha;

#ifdef DEBUG
  printf("screen_to_screen_blt():\n");
  printf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty);
  printf("width=%d height=%d\n", width, height);
#endif
  
  cmd32 = 0xcc430000;
  
  outpw(REG_2D_GEC, cmd32);

  if (srcx > destx) //+X
  {
    if (srcy > desty) //+Y
    {
      //printf("PP\n");
      direction = PP; // 000
    } 
    else //-Y
    {
      //printf("PN\n");
      direction= PN; // 100
      cmd32 |= 0x08; 
      srcy = srcy + height - 1;
      desty = desty + height - 1;
    }
  }      
  else //-X
  {     
    if (srcy > desty) //+Y
    {
      //printf("NP\n");
      direction = NP;
      cmd32 |= 0x04; // 010
      srcx = srcx + width - 1;
      destx = destx + width - 1;
    }  
    else //-Y
    {
      //printf("NN\n");
      direction = NN;
#if 1      
      cmd32 |= 0xc; // 110
      srcx = srcx + width - 1;
      destx = destx + width - 1;
      srcy = srcy + height - 1;
      desty = desty + height - 1;
#endif      
      //cmd32 &= 0xFFFFFFF1; // 000 //cmn
      
    }
   }     

#ifdef DEBUG
  printf("new srcx=%d srcy=%d\n", srcx, srcy);
  printf("new destx=%d desty=%d\n", destx, desty);
#endif  

  outpw(REG_2D_GEC, cmd32); 
  
  pitch = GFX_WIDTH << 16 | GFX_WIDTH; 
  outpw(REG_2D_GESDP, pitch);

  src_start = srcy << 16 | srcx;
  outpw(REG_2D_GESSXYL, src_start);
  
  dest_start = desty << 16 | destx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dimension);  
  
  //
  // force to use the same starting address
  //
  outpw(REG_2D_GEXYSORG, (int)GFX_START_ADDR);
  outpw(REG_2D_GEXYDORG, (int)GFX_START_ADDR);  //smf
  
  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }  

  if (_DrawMode==MODE_TRANSPARENT)
  {
    cmd32 |= 0x00008000; // color transparency 
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GETC, _ColorKey);
    outpw(REG_2D_GETCM, _ColorKeyMask);
  }  
  else if (_DrawMode==MODE_DEST_TRANSPARENT)
  {
    cmd32 |= 0x00009000;   // destination pixels control transparency
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GETC, _ColorKey);
    outpw(REG_2D_GETCM, _ColorKeyMask);
  }
  
  if (_EnableAlpha)
  {
    cmd32 |= 0x00200000;
    outpw(REG_2D_GEC, cmd32);
    
    data32 = inpw(REG_2D_GEMC) & 0x0000ffff;
    alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
    data32 |= (alpha << 16);
    
    outpw(REG_2D_GEMC, data32);
  }
  
  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}

///////////////////////////////////////////////////////////////////////////////
//
// Function: screen_to_screen_rop_blt()
//
// Description:
//   Screen-to-Screen BitBlt with ROP option. 
//
///////////////////////////////////////////////////////////////////////////////
void screen_to_screen_rop_blt(int srcx, int srcy, int destx, int desty, int width, int height, int rop)
{
  int direction;
  UINT32 cmd32, pitch, dest_start, src_start, dimension;
  UINT32 data32, alpha;

#ifdef DEBUG
  printf("screen_to_screen_rop_blt():\n");
  printf("ROP=0x%x\n", rop);
  printf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty);
  printf("width=%d height=%d\n", width, height);
#endif  
  
  cmd32 = 0x00430000 | (rop << 24);
  
  if (_PatternType==TYPE_MONO)
  {
    cmd32 |= 0x00000010; // default is TYPE_COLOR
  }
   
  outpw(REG_2D_GEC, cmd32);

#if 1 // normalization
  if (srcx > destx) //+X
  {
    if (srcy > desty) //+Y
    {
      //printf("PP\n");
      direction = PP; // 000
    } 
    else //-Y
    {
      //printf("PN\n");
      direction= PN; // 100
      cmd32 |= 0x08; 
      srcy = srcy + height - 1;
      desty = desty + height - 1;
    }
  }      
  else //-X
  {     
    if (srcy > desty) //+Y
    {
      //printf("NP\n");
      direction = NP;
      cmd32 |= 0x04; // 010
      srcx = srcx + width - 1;
      destx = destx + width - 1;
    }  
    else //-Y
    {
      //printf("NN\n");
      direction = NN;
      cmd32 |= 0xc; // 110
      srcx = srcx + width - 1;
      destx = destx + width - 1;
      srcy = srcy + height - 1;
      desty = desty + height - 1;
    }
   }     
#endif

#ifdef DEBUG
  printf("new srcx=%d srcy=%d\n", srcx, srcy);
  printf("new destx=%d desty=%d\n", destx, desty);
#endif 
 
  outpw(REG_2D_GEC, cmd32); 
  
  pitch = GFX_WIDTH << 16 | GFX_WIDTH; // pitch in pixel
  outpw(REG_2D_GESDP, pitch);

  src_start = srcy << 16 | srcx;
  outpw(REG_2D_GESSXYL, src_start);
  
  dest_start = desty << 16 | destx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dimension);  
  
  //
  // force to use the same starting address
  //
  outpw(REG_2D_GEXYSORG, (int)GFX_START_ADDR);
  outpw(REG_2D_GEXYDORG, (int)GFX_START_ADDR);  //smf
  
  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }  

  if (_DrawMode==MODE_TRANSPARENT)
  {
    cmd32 |= 0x00008000; // color transparency 
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GETC, _ColorKey);
    outpw(REG_2D_GETCM, _ColorKeyMask);
  }  
  else if (_DrawMode==MODE_DEST_TRANSPARENT)
  {
    cmd32 |= 0x00009000;
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GETC, _ColorKey);
    outpw(REG_2D_GETCM, _ColorKeyMask);
  }
  
  if (_EnableAlpha)
  {
    cmd32 |= 0x00200000;
    outpw(REG_2D_GEC, cmd32);
    
    data32 = inpw(REG_2D_GEMC) & 0x0000ffff;
    alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
    data32 |= (alpha << 16);
    
    outpw(REG_2D_GEMC, data32);
  }

  // 
  // Hardware may halt in ROP=0x00 and 0xFF.
  // This bug must be avoided by hardware by setting
  // b15 = 1
  // b14 = 0
  // b12 = 1
  //
  if ((rop==0x00) || (rop==0xff))
  {
    cmd32 = (cmd32 & 0xffff0fff) | 0x00009000;
    outpw(REG_2D_GEC, cmd32);
  }
  
  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}

///////////////////////////////////////////////////////////////////////////////
//
// Function: source_to_destination_blt()
//
// Description:
//   Source_to_Destination_blt BitBlt with SRCCOPY. 
//
//   attention : before calling this function, it would set the source and destination origin starting place
///////////////////////////////////////////////////////////////////////////////
void source_to_destination_blt(int srcx, int srcy, int destx, int desty, int width, int height, int srcpitch, int destpitch)
{
  int direction;
  UINT32 cmd32, pitch, dest_start, src_start, dimension;
  UINT32 data32, alpha;

#ifdef DEBUG
  printf("source_to_destination_blt():\n");
  printf("(%d,%d)=>(%d,%d)\n", srcx, srcy, destx, desty);
  printf("width=%d height=%d\n", width, height);
#endif 
 
  cmd32 = 0xcc430000;
  
  outpw(REG_2D_GEC, cmd32);

  if (srcx > destx) //+X
  {
    if (srcy > desty) //+Y
    {
      //printf("PP\n");
      direction = PP; // 000
    } 
    else //-Y
    {
      //printf("PN\n");
      direction= PN; // 100
      cmd32 |= 0x08; 
      srcy = srcy + height - 1;
      desty = desty + height - 1;
    }
  }      
  else //-X
  {     
    if (srcy > desty) //+Y
    {
      //printf("NP\n");
      direction = NP;
      cmd32 |= 0x04; // 010
      srcx = srcx + width - 1;
      destx = destx + width - 1;
    }  
    else //-Y
    {
      //printf("NN\n");
      direction = NN;
#if 1      
      cmd32 |= 0xc; // 110
      srcx = srcx + width - 1;
      destx = destx + width - 1;
      srcy = srcy + height - 1;
      desty = desty + height - 1;
#endif      
      //cmd32 &= 0xFFFFFFF1; // 000 //cmn
      
    }
   }     

#ifdef DEBUG
  printf("new srcx=%d srcy=%d\n", srcx, srcy);
  printf("new destx=%d desty=%d\n", destx, desty);
#endif  

  outpw(REG_2D_GEC, cmd32); 
  
  pitch = destpitch << 16 | srcpitch; // pitch in pixel, back | GFX_WIDTH ??
  outpw(REG_2D_GESDP, pitch);

  src_start = srcy << 16 | srcx;
  outpw(REG_2D_GESSXYL, src_start);
  
  dest_start = desty << 16 | destx;
  outpw(REG_2D_GEDSXYL, dest_start);
  
  dimension = height << 16 | width;
  outpw(REG_2D_GEDIXYL, dimension);  
  
  
  if (_ClipEnable)
  {
    cmd32 |= 0x00000200;
    if (_OutsideClip)
    {
      cmd32 |= 0x00000100;
    }
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GECBTL, _ClipTL);
    outpw(REG_2D_GECBBR, _ClipBR);
  }  

  if (_DrawMode==MODE_TRANSPARENT)
  {
    cmd32 |= 0x00008000; // color transparency 
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GETC, _ColorKey);
    outpw(REG_2D_GETCM, _ColorKeyMask);
  }  
  else if (_DrawMode==MODE_DEST_TRANSPARENT)
  {
    cmd32 |= 0x00009000;   // destination pixels control transparency
    outpw(REG_2D_GEC, cmd32);
    outpw(REG_2D_GETC, _ColorKey);
    outpw(REG_2D_GETCM, _ColorKeyMask);
  }
  
  if (_EnableAlpha)
  {
    cmd32 |= 0x00200000;
    outpw(REG_2D_GEC, cmd32);
    
    data32 = inpw(REG_2D_GEMC) & 0x0000ffff;
    alpha = (UINT32)((_AlphaKs << 8) | _AlphaKd);
    data32 |= (alpha << 16);
    
    outpw(REG_2D_GEMC, data32);
  }
  
  outpw(REG_2D_GETG, 1); 
  
  while ((inpw(REG_2D_GEINTS)&0x01)==0); // wait for command complete  
  
  outpw(REG_2D_GEINTS, 1); // clear interrupt status
}
